package com.iring.service.common.impl;

import java.net.SocketException;
import java.time.LocalDate;
import java.util.List;

import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.iring.domain.config.prop.LocalConfigProperties;
import com.iring.domain.config.prop.SIPProperties;
import com.iring.domain.config.prop.UDPProperties;
import com.iring.domain.config.prop.VOSPhoneProperties;
import com.iring.dao.common.DeviceDao;
import com.iring.dao.common.ProxyDao;
import com.iring.dao.common.UserDao;
import com.iring.dao.common.view.DeviceInfoViewDao;
import com.iring.dao.vos.CommonVosDao;
import com.iring.dao.vos.GetPhoneDao;
import com.iring.domain.common.DeviceInfo;
import com.iring.domain.common.ProxyInfo;
import com.iring.domain.common.User;
import com.iring.domain.common.view.DeviceInfoView;
import com.iring.domain.config.UDPEnum;
import com.iring.domain.pbx.udpsend.DdnsInfo;
import com.iring.domain.pbx.udpsend.ParamVO;
import com.iring.domain.pbx.udpsend.TrunkInfo;
import com.iring.domain.pbx.udpsend.UdpTaskInfo;
import com.iring.domain.pbx.udpsend.VpnInfo;
import com.iring.domain.sms.SMS;
import com.iring.domain.vos.phone.GetPhone;
import com.iring.domain.vos.phone.Phone;
import com.iring.domain.vos.phone.VosPhone;
import com.iring.exception.ParamInvalidException;
import com.iring.exception.config.ErrorEnum;
import com.iring.service.common.DeviceService;
import com.iring.service.common.DeviceTrunkService;
import com.iring.service.pbx.UdpService;
import com.iring.service.proxy.ProxyService;
import com.iring.service.sms.MessageService;
import com.iring.util.common.CommonUtil;
import com.iring.util.common.DateUtil;
import com.iring.util.common.IPUtils;
import com.iring.util.common.PasswordEncoderUtil;
import com.iring.util.common.StringUtil;
import com.iring.vo.common.device.CheckDomainVO;
import com.iring.vo.common.device.DeviceDdnsVO;
import com.iring.vo.common.device.DeviceUsernameVO;
import com.iring.vo.common.device.MacVO;
import com.iring.vo.common.device.ModDeviceVO;
import com.iring.vo.pbx.PBXDeviceInfo;
import com.iring.vo.pbx.PBXRes;
import com.iring.vo.pbx.UploadDevice;
import com.iring.vo.sms.SMSSendVO;


/**
 * @author  wanggan
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    private static final Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);

    @Autowired
    DeviceDao deviceDao;

    @Autowired
    VOSPhoneProperties vosPhoneProperties;

    @Autowired
    DeviceTrunkService deviceTrunkService;

    @Autowired
    DeviceInfoViewDao deviceInfoViewDao;

    @Autowired
    LocalConfigProperties localUserProperties;

    @Autowired
    UDPProperties udpProperties;

    @Autowired
    MessageService messageService;

    @Autowired
    CommonVosDao commonVosDao;

    @Autowired
    GetPhoneDao getPhoneDao;

    @Autowired
    UdpService udpUtil;

    @Autowired
    ProxyDao sipDao;

    @Autowired
    ProxyService sipService;

    @Autowired
    PasswordEncoderUtil passwordEncoder;

    @Autowired
    SIPProperties sipProperties;

    @Autowired
    UserDao userDao;

    @Autowired
    ProxyDao proxyDao;

    @Autowired
    CommonUtil commonUtil;

    private void checkStringParam(String str, String name) {
        if (StringUtil.isEmpty(str)) {
            throw new ParamInvalidException(name + " is null");
        }
    }

    private void checkCodeParam(String code) {
        if (StringUtil.isEmpty(code)) {
            throw new ParamInvalidException("code is null");
        } else if (code.length() <= 3) {
            throw new ParamInvalidException("invalid code length");
        }
    }

    private void checkPhoneParam(String contactPhonenum){
        checkStringParam(contactPhonenum, "contactPhonenum");

        Boolean isphone = commonUtil.checkPhone(contactPhonenum);
        if(!isphone){
            throw new ParamInvalidException("invalid phone number format");
        }
    }

    @Override
    public List<DeviceInfoView> listDevice(String username) {
        return deviceInfoViewDao.findByUsername(username);
    }

    @Override
    public DeviceInfo findByMac(String mac) {
        return deviceDao.findByMac(mac);
    }

    @Override
    public DeviceInfoView getDeviceInfo(Integer id, String username) {
        if (StringUtil.isEmpty(id)) {
            throw new ParamInvalidException("dId is null");
        }
        return deviceInfoViewDao.findByIdAndUsername(id, username);
    }

    @Override
    public String checkNetwork(DeviceInfo deviceInfo) {
        String type = UDPEnum.REQ_NETWORK.getValue();
        VpnInfo vpnInfo = new VpnInfo(1);
        UdpTaskInfo udpTaskInfo = new UdpTaskInfo();
        udpTaskInfo.setVpnvo(vpnInfo);
        udpTaskInfo.setType(type);
        return getClientResult(deviceInfo, udpTaskInfo);
    }

    @Override
    public String openRemoteLink(DeviceInfo deviceInfo) {
        String type = UDPEnum.REQ_VPN.getValue();
        String vpnIp = getRandomVpnIp();
        deviceInfo.setVpnIp(vpnIp);
        // 更新到数据库中
        deviceInfo = deviceDao.save(deviceInfo);
        logger.info("update username={},device mac={} vpn_ip success={}", deviceInfo.getUsername(),deviceInfo.getMac());

        String vpnUsername = localUserProperties.getVpnUsername();
        String vpnPassword = localUserProperties.getVpnPassword();
        String vpnPort = localUserProperties.getVpnPort();

        VpnInfo vpnInfo = new VpnInfo(1, vpnIp, vpnUsername, vpnPassword, vpnPort);
        UdpTaskInfo udpTaskInfo = new UdpTaskInfo();
        udpTaskInfo.setVpnvo(vpnInfo);
        udpTaskInfo.setType(type);

        return getClientResult(deviceInfo, udpTaskInfo);
    }

    public String closeRemoteLink(DeviceInfo deviceInfo) {
        String type = UDPEnum.REQ_VPN.getValue();
        VpnInfo vpnInfo = new VpnInfo(0);
        UdpTaskInfo udpTaskInfo = new UdpTaskInfo();
        udpTaskInfo.setVpnvo(vpnInfo);
        udpTaskInfo.setType(type);

        String result = getClientResult(deviceInfo, udpTaskInfo);

        String vpnIp = deviceInfo.getVpnIp();
        if (!StringUtil.isEmpty(vpnIp)) {
            deviceInfo.setVpnIp("");
            deviceInfo = deviceDao.save(deviceInfo);
            logger.info("clean username={},mac={}vpn_ip info success",deviceInfo.getUsername(),deviceInfo.getMac());
        }
        return result;
    }

    public String getClientResult(DeviceInfo deviceInfo,UdpTaskInfo udpTaskInfo) {
        String mac = deviceInfo.getMac();
        String clientip = deviceInfo.getPublicIp();
        Integer clientport = deviceInfo.getPublicPort();
        if (null == clientip || null == clientport) {
            throw new ParamInvalidException(ErrorEnum.LINK_FAILED);
        }
        Integer randPort = udpUtil.getRandomPort();
        udpTaskInfo.setRandomport(randPort);

        Integer serverport = udpProperties.getPort();
        ParamVO paramVO = new ParamVO(mac, clientip, clientport, serverport, udpTaskInfo);
        Integer status = -1;
        try {
            status = udpUtil.sendToClientStatus(paramVO);
            if (status == 0) {
                return status.toString();
            }else if(status == 14) {
                throw new ParamInvalidException(ErrorEnum.DDNS_ALREADY_EXIST);
            }else if (status == -1 || status == 1) {
                throw new ParamInvalidException(ErrorEnum.LINK_FAILED);
            }
        } catch (SocketException e) {
            logger.info("exception={}", e);
        }
        return status.toString();
    }


    public Integer getClientResultInt(DeviceInfo deviceInfo, UdpTaskInfo udpTaskInfo) throws SocketException {
        String mac = deviceInfo.getMac();
        String clientip = deviceInfo.getPublicIp();
        Integer clientport = deviceInfo.getPublicPort();
        if (null == clientip || null == clientport) {
            throw new ParamInvalidException(ErrorEnum.LINK_FAILED);
        }
        Integer randPort = udpUtil.getRandomPort();
        udpTaskInfo.setRandomport(randPort);

        Integer serverport = udpProperties.getPort();
        ParamVO paramVO = new ParamVO(mac, clientip, clientport, serverport, udpTaskInfo);
        return udpUtil.sendToClientStatus(paramVO);
    }

    @Override
    public DeviceInfo findDeviceState(MacVO macVO, String username) {
        String mac = macVO.getMac();
        checkStringParam(mac,"mac");
        DeviceInfo deviceInfo = deviceDao.findByMacAndUsername(mac,username);
        if (null == deviceInfo) {
            throw new ParamInvalidException(ErrorEnum.INVALID_MAC);
        }
        // 设备在线才能进行访问
        if (deviceInfo.getIsOnline() == 1) {
            // 检查是否进行比较版本
            if (udpProperties.getCompare()) {
                if ((udpProperties.getVersion()
                        .compareTo(deviceInfo.getVersion()) >= 0)) {
                    // 如果当前系统的版本大于等于设备的版本
                    return deviceInfo;
                }
                throw new ParamInvalidException(ErrorEnum.CURRENT_VERSION_DIFF);
            } else {
                return deviceInfo;
            }
        }
        throw new ParamInvalidException(ErrorEnum.DEVICE_OFFLINE);
    }

    @Override
    public DeviceInfo updateDeviceStatus(String mac, String ip, Integer port) {
        if(StringUtil.isEmpty(mac)){
            return null;
        }
        DeviceInfo deviceInfo = deviceDao.findByMac(mac);
        if (null == deviceInfo) {
            return null;
        }
        deviceInfo.setPublicIp(ip);
        deviceInfo.setPublicPort(port);
        deviceInfo.setIsOnline(1);
        deviceInfo.setUpdateTime(DateUtil.getDate());
        deviceInfo = deviceDao.save(deviceInfo);
        return deviceInfo;
    }

    @Override
    public String isDdnsAvaliablle(String username, MacVO macVO) {
        String mac = macVO.getMac();
        checkStringParam(mac,"mac");
        User user = userDao.findByUsername(username);
        isModProxy(mac,username);
        return commonUtil.dealContactPhoneNumber(user.getContactPhonenum());
    }

    @Override
    public Boolean checkDdnsAvaliablle(String username, CheckDomainVO checkDomainVO) {
        String deviceDomain = checkDomainVO.getDeviceDomain();

        if (null == deviceDomain || deviceDomain.trim().equals("")) {
            throw new ParamInvalidException("deviceDomain is null");
        }else if(!commonUtil.checkDeviceDomain(deviceDomain)){
            throw new ParamInvalidException("invalid deviceDomain");
        }
        DeviceInfo deviceInfo = deviceDao.findDistinctByDeviceDomain(deviceDomain);
        if(null == deviceInfo){
            return Boolean.TRUE;
        }
        throw new ParamInvalidException(ErrorEnum.DDNS_ALREADY_EXIST);
    }

    @Override
    public Boolean sendDdnsVerifyCode(String username) {
        User user = userDao.findByUsername(username);
        String countryCode = user.getContactPhonenum().split("-")[0];
        String contactPhonenum = user.getContactPhonenum().split("-")[1];

        SMS sms = new SMS(contactPhonenum, countryCode);
        Boolean isSend = messageService.sendCode(sms);
        if (isSend) {
            user.setSmsState(1);
        } else {
            user.setSmsState(0);
            userDao.save(user);
            throw new ParamInvalidException(ErrorEnum.NETWORK_EXCEPTION);
        }
        userDao.save(user);
        return isSend;
    }

    @Override
    public Boolean updateDeviceUsername(DeviceUsernameVO deviceUsernameVO, String username) {
        Integer dId = deviceUsernameVO.getId();
        if (null == dId) {
            throw new ParamInvalidException("id is null");
        }
        String deviceUsername = deviceUsernameVO.getDeviceUsername();

        checkStringParam(deviceUsername,"deviceUsername");
        List<DeviceInfo> infoList = deviceDao.findByUsernameAndDeviceUsername(username,deviceUsername);

        if(infoList.size() > 0){
            throw new ParamInvalidException(ErrorEnum.DUPLICATE_DEVICEUSERNAME);
        }

        DeviceInfo deviceInfo = deviceDao.findByIdAndUsername(dId, username);
        if (null == deviceInfo) {
            throw new ParamInvalidException(ErrorEnum.MODIFY_FAILED);
        }
        deviceInfo.setDeviceUsername(deviceUsername);
        deviceInfo = deviceDao.save(deviceInfo);
        logger.info("update device username success = {}", deviceInfo);
        return Boolean.TRUE;
    }

    private Boolean isModProxy(String mac,String username){
        ProxyInfo proxyInfo = sipDao.findByMacAndUsernameAndSendStatusIsTrue(mac,username);
        if(null == proxyInfo){
            return true;
        }
        LocalDate lastMod = DateUtil.toLocalDate(proxyInfo.getGmtUpdateTime());
        LocalDate now = LocalDate.now();
        Long ddnsPeriod =localUserProperties.getDdnsPeriod();
        if(lastMod.plusDays(ddnsPeriod).isAfter(now)){
            throw new ParamInvalidException("301","modify peroid must be more than "+ddnsPeriod+" days");
        }
        return true;
    }
    @Override
    public Boolean updateDeviceDdns(DeviceDdnsVO deviceDdnsVO, String username) {
        Integer dId = deviceDdnsVO.getId();
        if (null == dId) {
            throw new ParamInvalidException("id is null");
        }
        String deviceDomain = deviceDdnsVO.getDeviceDomain();

        if (StringUtil.isEmpty(deviceDomain)) {
            throw new ParamInvalidException("deviceDomain is null");
        }else if(!commonUtil.checkDeviceDomain(deviceDomain)){
            throw new ParamInvalidException("invalid deviceDomain");
        }
        String code = deviceDdnsVO.getCode();
        checkCodeParam(code);

        DeviceInfo deviceInfo = deviceDao.findByIdAndUsername(dId, username);
        if (null == deviceInfo) {
            throw new ParamInvalidException(ErrorEnum.USER_NOT_AUTHENTION);
        }

        String mac = deviceInfo.getMac();

        //判断是否可以修改
        isModProxy(mac,username);

        DeviceInfo deviceDomain1 = deviceDao.findDistinctByDeviceDomain(deviceDomain);
        if(deviceDomain1 instanceof DeviceInfo){
            throw new ParamInvalidException(ErrorEnum.DDNS_ALREADY_EXIST);
        }

        //校验短信状态
        User user = userDao.findByUsername(username);
        if(user.getSmsState() != 1) {
            throw new ParamInvalidException("please get a sms code first");
        }
        String countryCode = user.getContactPhonenum().split("-")[0];
        String contactPhonenum = user.getContactPhonenum().split("-")[1];

        SMS sms = new SMS(contactPhonenum, countryCode, code);
        messageService.checkCode(sms);
        //操作sip

        ProxyInfo proxyInfo = doProxy(mac,username, deviceDomain);
        if (null == proxyInfo) {
            throw new ParamInvalidException(ErrorEnum.MODIFY_FAILED);
        }
        String type = UDPEnum.REQ_DDNS.getValue();
        DdnsInfo ddnsInfo = new DdnsInfo();
        ddnsInfo.setProxy_realm(proxyInfo.getProxyRealm());
        ddnsInfo.setDdns_domain(deviceDomain);
        ddnsInfo.setProxy_port(proxyInfo.getProxyPort());
        ddnsInfo.setProxy_username(proxyInfo.getProxyUsername());
        ddnsInfo.setProxy_password(proxyInfo.getProxyPassword());
        UdpTaskInfo udpTaskInfo = new UdpTaskInfo();
        udpTaskInfo.setType(type);
        udpTaskInfo.setDdnsvo(ddnsInfo);

        String result = getClientResult(deviceInfo,udpTaskInfo);
        if ("0".equals(result)) {// 如果返回0才进行更新
            Integer status = sipDao.updateDeviceDomain(mac,username);
            if(status == 1){
                logger.info("username={} update  device mac={} ddns info success={}",username,mac,deviceDomain);
                return Boolean.TRUE;
            }
        }
        throw new ParamInvalidException(ErrorEnum.MODIFY_FAILED);
    }

    /**
     * 对sip proxy中继进行处理,如果存在,则进行下发pbx,如果不存在,则创建sip,并下发pbx
     *
     * @param mac
     *          mac地址
     * @param username
     *          用户名
     * @param ddns
     *          用户修改的ddns域名
     * @return  是否创建远程sip成功,创建成功返回代理的对象
     * 创建失败返回<code>null</code>
     */
    private ProxyInfo doProxy(String mac,String username,String ddns){
        ProxyInfo sipInfo = sipDao.findByMacAndUsername(mac,username);
        if(null == sipInfo){
            //如果没有记录,则进行创建
            //生成用户名
            String proxy_username = createValidProxyUsername(mac);
            if(null == proxy_username){
                return null;
            }
            //生成密码
            String proxy_password = StringUtil.getRandomString(16);
            //先进行本地保存
            ProxyInfo proxyInfo = createProxyInfo(mac,username,proxy_username,proxy_password,ddns);
            logger.info("create proxy info success={}",proxyInfo);

            //可以进行创建
            Boolean isCreate = sipService.createSipAccount(proxy_username,proxy_password);
            if(null == isCreate){
                return null;
            }
            if(isCreate) {
                logger.info("create proxy account success");
                return proxyInfo;
            }
        }else {
            //检查代理用户,如果存在,则判断发送状态,如果未发送,则直接进行修改,如果已经发送,则新建一条
            String proxy_username = sipInfo.getProxyUsername();
            String proxy_password = sipInfo.getProxyPassword();
            Boolean isExist = sipService.isSipUsernameExist(proxy_username);
            if (null == isExist) {
                return null;
            }
            if (!isExist) {
                //本地存在,sip不存在,则进行创建
                Boolean isCreate = sipService.createSipAccount(proxy_username, proxy_password);
                if (null == isCreate || !isCreate) {
                    return null;
                }
            }

            if (sipInfo.getSendStatus()) {
                //如果已经有记录,并且已经发送,新建一条记录
                ProxyInfo proxyInfo = createProxyInfo(mac, username, proxy_username, proxy_password, ddns);
                logger.info("create proxy account success={}", proxyInfo);
                return proxyInfo;
            } else {
                //如果有记录,但是发送状态为未发送,则直接覆盖
                sipInfo.setProxyPort(sipProperties.getProxyPort());
                sipInfo.setProxyRealm(sipProperties.getProxyRealm());
                sipInfo.setProxyUri(ddns);
                sipInfo.setSendStatus(false);
                sipInfo.setGmtCreateTime(null);
                sipInfo = sipDao.save(sipInfo);
                logger.info("update proxy account success={}", sipInfo);
                return sipInfo;
            }
        }
        return null;
    }

    private ProxyInfo createProxyInfo(String mac,String username,String proxy_username,String proxy_password,String ddns){
        ProxyInfo proxyInfo = new ProxyInfo();
        proxyInfo.setMac(mac);
        proxyInfo.setUsername(username);
        proxyInfo.setProxyUsername(proxy_username);
        proxyInfo.setProxyPassword(proxy_password);
        proxyInfo.setProxyPort(sipProperties.getProxyPort());
        proxyInfo.setProxyRealm(sipProperties.getProxyRealm());
        proxyInfo.setProxyUri(ddns);
        proxyInfo.setSendStatus(false);
        proxyInfo.setGmtCreateTime(null);
        proxyInfo = sipDao.save(proxyInfo);
        return proxyInfo;
    }
    private String createValidProxyUsername(String mac){
        //产生代理用户名,查询本地,如果本地没有,则查询proxy是否存在,
        String proxy_username = (mac + StringUtil.getRandomString(4)).toLowerCase();
        Integer count = 0;
        while(count<5){
            ProxyInfo proxyInfo = sipDao.findDistinctByProxyUsername(proxy_username);
            //如果本地查找为空,则进行proxy查询
            if(null == proxyInfo){
                Boolean isProxyExist = sipService.isSipUsernameExist(proxy_username);
                if(isProxyExist instanceof  Boolean){
                    if(!isProxyExist){
                        return proxy_username;
                    }
                }
            }
            proxy_username = (mac + StringUtil.getRandomString(4)).toLowerCase();
            count++;
        }
        return null;
    }

    @Override
    public Boolean isIringtelNumAvailable(SMSSendVO SMSSendVO) {
        String countryCode = SMSSendVO.getCountryCode();
        checkStringParam(countryCode, "countryCode");

        String contactPhonenum = SMSSendVO.getContactPhonenum();
        checkStringParam(contactPhonenum, "contactPhonenum");

        // vos 请求话机数据是否存在
        String e164s = countryCode + contactPhonenum;
        GetPhone getPhone = getPhoneDao.getPhoneInfo(new Phone(new String[] { e164s }));
        if (getPhone.getInfoPhones().size() > 0) {
            logger.info("exist e164={}", getPhone);
            throw new ParamInvalidException(ErrorEnum.INVALID_IRINGTEL_NUMBER);
        }
        return Boolean.TRUE;
    }

    @Override
    public Boolean sendValidCode(SMSSendVO SMSSendVO) {
        String countryCode = SMSSendVO.getCountryCode();
        checkStringParam(countryCode, "countryCode");

        String contactPhonenum = SMSSendVO.getContactPhonenum();
        checkStringParam(contactPhonenum, "contactPhonenum");

        SMS sms = new SMS(contactPhonenum, countryCode);
        Boolean isSend = messageService.sendCode(sms);
        if(isSend){
            return isSend;
        }else {
            throw new ParamInvalidException(ErrorEnum.NETWORK_EXCEPTION);
        }
    }

    @Override
    public Boolean updateDeviceIringtelNum(ModDeviceVO modDeviceVO) {
        String mac = modDeviceVO.getMac();
        checkStringParam(mac, "mac");

        String countryCode = modDeviceVO.getCountryCode();
        checkStringParam(countryCode, "countryCode");

        String contactPhonenum = modDeviceVO.getContactPhonenum();
        checkStringParam(contactPhonenum, "contactPhonenum");

        String code = modDeviceVO.getCode();
        checkCodeParam(code);

        DeviceInfo deviceInfo = deviceDao.findByMac(mac);
        if (null == deviceInfo) {
            throw new ParamInvalidException(ErrorEnum.INVALID_MAC);
        }
        SMS sms = new SMS(contactPhonenum, countryCode, code);
        messageService.checkCode(sms);
        return updateIringNum(deviceInfo, countryCode+contactPhonenum);
    }

    @Transactional
    @Override
    public PBXRes addDevice(UploadDevice uploadDevice) {
        String type = uploadDevice.getType();
        if (null == type || type.trim().equals("") ||!"deviceinfo".equals(type)) {
            return new PBXRes(201, "invalid device mark");
        }
        PBXDeviceInfo pbxDeviceInfo = uploadDevice.getInfo();
        String account = pbxDeviceInfo.getIring_account();

        if (null == account || account.trim().equals("")) {
            account = "";
        }
        String mac = pbxDeviceInfo.getMac();
        if (null == mac || mac.trim().equals("")) {
            return new PBXRes(203, "mac is null");
        }

        DeviceInfo deviceInfo = deviceDao.findByMac(mac);
        if (null == deviceInfo) {
            DeviceInfo dev = new DeviceInfo();
            dev.setMac(mac);
            dev.setUsername(account);
            dev.setIringtelNum(pbxDeviceInfo.getIring_trunknumber());
            dev.setDevicekind(pbxDeviceInfo.getDevicemodel_id());
            dev.setTrunkOnline(pbxDeviceInfo.getTrunk_online());
            dev.setVpnIp(pbxDeviceInfo.getVpn_ip());
            dev.setVpnStatus(pbxDeviceInfo.getVpn_status());

            dev.setIsOnline(pbxDeviceInfo.getDevice_online());
            dev.setPriviteLanIp(pbxDeviceInfo.getPrivite_lan_ip());
            dev.setPriviteWanIp(pbxDeviceInfo.getPrivite_wan_ip());
            dev.setVersion(pbxDeviceInfo.getSystem_version());

            dev.setUpdateTime(DateUtil.getDate());
            dev.setProxyOnline(pbxDeviceInfo.getProxy_online());
            dev = deviceDao.save(dev);
            logger.info("add device info success={}", dev);

        } else {// 如果设备信息不为空,进行更新 13

            String iringnum = pbxDeviceInfo.getIring_trunknumber();
            deviceInfo.setMac(mac);
            deviceInfo.setUsername(account);
            deviceInfo.setDevicekind(pbxDeviceInfo.getDevicemodel_id());
            deviceInfo.setTrunkOnline(pbxDeviceInfo.getTrunk_online());
            deviceInfo.setIsOnline(pbxDeviceInfo.getDevice_online());
            deviceInfo.setUpdateTime(DateUtil.getDate());

            deviceInfo.setPriviteLanIp(pbxDeviceInfo.getPrivite_lan_ip());
            deviceInfo.setPriviteWanIp(pbxDeviceInfo.getPrivite_wan_ip());
            deviceInfo.setVersion(pbxDeviceInfo.getSystem_version());
            deviceInfo.setVpnStatus(pbxDeviceInfo.getVpn_status());
            deviceInfo.setIringtelNum(iringnum);
            deviceInfo.setProxyOnline(pbxDeviceInfo.getProxy_online());
            deviceDao.save(deviceInfo);
        }
        return new PBXRes();
    }

    private Boolean createNewPhone(DeviceInfo deviceInfo, String newphone) {
        // 创建新话机
        String username = deviceInfo.getUsername();
        String mac = deviceInfo.getMac();
        VosPhone vosPhone = createVosPhone(newphone, username);
        if(null == vosPhone){
            return Boolean.FALSE;
        }
        // 获取新的话机密码
        String newpass = vosPhone.getPassword();

        String type = UDPEnum.REQ_TRUNKNUM.getValue();
        TrunkInfo trunkInfo = new TrunkInfo(newphone, newpass);

        UdpTaskInfo udpTaskInfo = new UdpTaskInfo();
        udpTaskInfo.setType(type);
        udpTaskInfo.setTrunkvo(trunkInfo);

        Integer result = null;
        try {
            result = getClientResultInt(deviceInfo,udpTaskInfo);
        } catch (SocketException e) {
            // 如果客户端修改话机失败或者本地更新话机号码失败,删除vos的话机
            deleteVosPhone(newphone);
            logger.info("client update phone fail,remove user={}phone={}success", username, newphone);
        }
        // 处理pbx返回的结果
        if (result == 0) {// 如果返回0成功，修改本地,返回其他,修改失败,删除vos创建的话机
            Integer res = deviceDao.updateDeviceInfo(mac, username, newphone, newpass,
                    localUserProperties.getNationalSid());
            if (res == 1) {
                logger.info("update local phone ={} success",newphone);
                return Boolean.TRUE;
            }
        }
        // 如果客户端修改话机失败或者本地更新话机号码失败,删除vos的话机
        return deleteVosPhone(newphone);
    }

    private Boolean deleteVosPhone(String iringnum){
        Boolean isDelete = commonVosDao.deletePhone(iringnum);
        if (isDelete) {// 删除成功
            return Boolean.TRUE;
        }
        throw new ParamInvalidException(ErrorEnum.MODIFY_FAILED);
    }

    private Boolean updateIringNum(DeviceInfo deviceInfo, String newphone) {
        // 删除话机
        String iringnum = deviceInfo.getIringtelNum();
        if(null != iringnum && !iringnum.trim().equals("")){
            deleteVosPhone(iringnum);
        }
        return createNewPhone(deviceInfo, newphone);
    }

    /**
     * 创建新话机
     *
     * @param newphone
     *            新的话机号码
     * @param username
     *            用户名
     * @return {@link VosPhone}
     */
    public VosPhone createVosPhone(String newphone, String username) {
        VosPhone vosPhone = new VosPhone();
        vosPhone.setAutoCreateAccount(vosPhoneProperties.getAutoCreateAccount());
        vosPhone.setE164(newphone);
        vosPhone.setCallLevel(vosPhoneProperties.getCallLevel());
        vosPhone.setAccount(username);
        vosPhone.setPassword(StringUtil.getRandomString(16));
        vosPhone.setFeerateGroup(vosPhoneProperties.getFeerateGroup());
        vosPhone.setMonthlyMoneyMinimum(vosPhoneProperties.getMonthlyMoneyMinimum());
        Boolean isCreate = commonVosDao.createVosPhone(vosPhone);
        if (isCreate) {// 创建话机成功
            logger.info("create vos e164s success");
            return vosPhone;
        }
        return null;
    }

    /**
     * 查询vpnip是否已经使用
     *
     * @param vpnip
     *            vpnip
     * @return 是否被使用
     */
    private Boolean vpnIPAccess(String vpnip) {
        DeviceInfo deviceInfo = deviceDao.findDistinctByVpnIp(vpnip);
        if (deviceInfo == null) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

    private String getRandomVpnIp() {
        String vpnIp = IPUtils.getRandomIp();
        while (!vpnIPAccess(vpnIp)) {
            vpnIp = IPUtils.getRandomIp();
        }
        return vpnIp;
    }
}
